package com.tvunetworks.center.user.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.user.mapper.RoleUserMapper;
import com.tvunetworks.center.user.model.RoleUser;
import com.tvunetworks.center.user.model.User;
import com.tvunetworks.center.user.model.param.AddRoleUserParam;
import com.tvunetworks.center.user.model.param.GetSonUserNoRelationRoleIdParam;
import com.tvunetworks.center.user.model.param.GetUserByRoleIdParam;
import com.tvunetworks.center.user.model.result.ResultConstant;
import com.tvunetworks.center.user.model.vo.RoleUserVo;
import com.tvunetworks.center.user.model.vo.RoleVo;
import com.tvunetworks.center.user.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Etan Yang
 * @data: 2021/4/9 16:34
 * @program: tvucc-aggregator
 * @description:
 */

@Service
@Slf4j
public class RoleUserServiceImpl extends BaseService<RoleUser> implements RoleUserService {
    @Autowired
    private RoleUserMapper roleUserMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private RoleManagementService roleManagementService;
    @Autowired
    private UserFeatureService userFeatureService;
    @Autowired
    private UserDeviceService userDeviceService;

    @Override
    public List<RoleUser> getByRoleId(String roleId) {
        return roleUserMapper.getByRoleId(roleId);
    }

    @Override
    public int deleteByRoleId(String roleId) {
        return roleUserMapper.deleteByRoleId(roleId);
    }

    @Override
    public int addRoleUser(String roleId, String userId) {
        RoleUser roleUser = new RoleUser()
                .setRoleId(roleId)
                .setUserId(userId);
        return super.insert(roleUser);
    }

    @Override
    public RoleUser getByUserId(String userId) {
        return roleUserMapper.getByUserId(userId);
    }

    @Override
    public int deleteByRoleUser(RoleUser roleUser) {
        return super.deleteLogicByWhere(roleUser);
    }

    @Override
    public RoleUserVo getUserRoleVoByUserId(String userId) {
        return roleUserMapper.getUserRoleVoByUserId(userId);
    }

    @Override
    public Result<Object> pageUserByRoleId(LoginUser loginUser, GetUserByRoleIdParam param) {
        if (!LocalConstant.UserRole.ADMIN.equalsIgnoreCase(loginUser.getRole())) {
            return ResultConstant.RoleManagement.ADMIN_PERMISSION;
        }
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        return ResultUtil.success(new PageInfo<>(roleUserMapper.pageUserByRoleId(param)));
    }

    @Override
    @Transactional
    public Result<Object> add(LoginUser loginUser, AddRoleUserParam param) {
        //1.校验用户是否合法
        if (!LocalConstant.UserRole.ADMIN.equalsIgnoreCase(loginUser.getRole())) {
            return ResultConstant.RoleManagement.ADMIN_PERMISSION;
        }
        String userId = param.getUserId();
        String roleId = param.getRoleId();
        User user = userService.getById(userId);
        if (user == null || !StringUtils.equals(LocalConstant.UserRole.USER, user.getRole())
                || StringUtils.isEmpty(user.getUserParentId()) || !StringUtils.equals(user.getUserParentId(), loginUser.getId())) {
            return ResultConstant.RoleUser.USER_NOT_EXIST_OR_NOT_BELONG_ACCOUNT;
        }
        User byId = userService.getById(user.getUserParentId());
        if (byId == null) {
            return ResultConstant.RoleUser.USER_PARENT_ACCOUNT_NOT_EXIST;
        }
        //2.若用户没有role或者与已有的role不同
        RoleVo role = roleManagementService.getRoleByRoleId(roleId, loginUser.getId());
        if (role == null) {
            return ResultConstant.RoleUser.ROLE_NOT_EXIST_OR_NOT_BELONG_ACCOUNT;
        }
        RoleUser roleUser = this.getByUserId(userId);
        if (roleUser != null && StringUtils.equals(roleUser.getRoleId(), roleId)) {
            return ResultConstant.RoleUser.ROLE_USER_RELATION_ALREADY_HAVE_EXIST;
        }
        if (roleUser == null || !StringUtils.equals(roleUser.getRoleId(), roleId)) {
            //修改或添加roleUser
            if (roleUser == null) {
                this.addRoleUser(roleId, userId);
            }else {
                this.updateRoleIdByUserId(userId, roleId);
            }
            //修改user和feature的关系
            List<String> existFeatureIds = userFeatureService.listAllUserEnableFeatureIds(userId);
            if (CollectionUtils.isNotEmpty(existFeatureIds) && CollectionUtils.isNotEmpty(role.getFeatureIds())) {
                List<String> sameFeatureIds = existFeatureIds.stream().filter(s -> {
                    for (String featureId : role.getFeatureIds()) {
                        if (StringUtils.equals(featureId, s)) {
                            return true;
                        }
                    }
                    return false;
                }).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(sameFeatureIds)) {
                    existFeatureIds.removeAll(sameFeatureIds);
                    role.getFeatureIds().removeAll(sameFeatureIds);
                }
            }
            userFeatureService.addAndRemoveFeatureListByUserId(userId, user.getRole(), user.getUserParentId(), role.getFeatureIds(), existFeatureIds);
            //修改device和user的关系
            List<String> peerIds = userDeviceService.listUserCacheRids(userId);
            if (CollectionUtils.isNotEmpty(peerIds) && CollectionUtils.isNotEmpty(role.getPeerIds())) {
                List<String> samePeerIds = peerIds.stream().filter(s -> {
                    for (String peerId : role.getPeerIds()) {
                        if (StringUtils.equals(peerId, s)) {
                            return true;
                        }
                    }
                    return false;
                }).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(samePeerIds)) {
                    peerIds.removeAll(samePeerIds);
                    role.getPeerIds().removeAll(samePeerIds);
                }
            }
            List<String> userList = new ArrayList<>();
            userList.add(userId);
            String result = userDeviceService.unbindUserReceiverCenter(loginUser.getId(), peerIds, userList);
            if (StringUtils.isNotEmpty(result)) {
                return ResultUtil.error("0x1", result);
            }
            result = userDeviceService.bindUserReceiverCenter(loginUser.getId(), role.getPeerIds(), userList);
            if (StringUtils.isNotEmpty(result)) {
                return ResultUtil.error("0x1", result);
            }
        }
        return ResultUtil.success();
    }


    @Override
    public int updateRoleIdByUserId(String userId, String roleId) {
        return roleUserMapper.updateRoleIdByUserId(userId, roleId);
    }

    @Override
    public Result<Object> delete(LoginUser loginUser, String userId) {
        if (!LocalConstant.UserRole.ADMIN.equalsIgnoreCase(loginUser.getRole())) {
            return ResultConstant.RoleManagement.ADMIN_PERMISSION;
        }
        roleUserMapper.deleteByUserId(userId);
        return ResultUtil.success();
    }

    @Override
    public int deleteByUserId(String userId) {
        roleUserMapper.deleteByUserId(userId);
        return 0;
    }

    @Override
    public Result<Object> getSonUserNoRelationRoleId(LoginUser loginUser, GetSonUserNoRelationRoleIdParam param) {
        if (!LocalConstant.UserRole.ADMIN.equalsIgnoreCase(loginUser.getRole())) {
            return ResultConstant.RoleManagement.ADMIN_PERMISSION;
        }
        String loginUserId = loginUser.getId();
        param.setParentUserId(loginUserId);
        PageHelper.startPage(param.getPageNum(), param.getPageSize());

        return ResultUtil.success(new PageInfo<>(roleUserMapper.getSonUserNoRelationRoleId(param)));
    }

}
